package com.smart.community.region.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.smart.community.region.dto.RegionDTO;
import com.smart.community.region.dto.RegionQueryDTO;
import com.smart.community.region.dto.RegionStatsVO;
import com.smart.community.region.dto.RegionTreeVO;
import com.smart.community.region.dto.RegionVisualizationDTO;
import com.smart.community.region.entity.Region;

import java.math.BigDecimal;
import java.util.List;

/**
 * 区域服务接口
 * 
 * @author Wu.Liang
 * @since 2024-12-21
 */
public interface IRegionService extends IService<Region> {

    // ==================== 基础CRUD方法 ====================

    /**
     * 创建区域
     * 
     * @param regionDTO 区域信息
     * @return 是否成功
     */
    boolean createRegion(RegionDTO regionDTO) throws Exception;

    /**
     * 更新区域
     * 
     * @param regionDTO 区域信息
     * @return 是否成功
     */
    boolean updateRegion(RegionDTO regionDTO) throws Exception;

    /**
     * 删除区域
     * 
     * @param regionId 区域ID
     * @return 是否成功
     */
    boolean deleteRegion(Long regionId) throws Exception;

    /**
     * 批量删除区域
     * 
     * @param regionIds 区域ID列表
     * @return 是否成功
     */
    boolean batchDeleteRegions(List<Long> regionIds) throws Exception;

    /**
     * 更新区域状态
     * 
     * @param regionId 区域ID
     * @param status 状态
     * @return 是否成功
     */
    boolean updateRegionStatus(Long regionId, Integer status) throws Exception;

    /**
     * 批量更新区域状态
     * 
     * @param regionIds 区域ID列表
     * @param status 状态
     * @return 是否成功
     */
    boolean batchUpdateRegionStatus(List<Long> regionIds, Integer status) throws Exception;

    // ==================== 查询方法 ====================

    /**
     * 分页查询区域列表
     * 
     * @param queryDTO 查询条件
     * @return 分页结果
     */
    IPage<Region> getRegionPage(RegionQueryDTO queryDTO) throws Exception;

    /**
     * 获取区域详情
     * 
     * @param regionId 区域ID
     * @return 区域详情
     */
    Region getRegionDetail(Long regionId) throws Exception;

    /**
     * 根据区域编码获取区域
     * 
     * @param regionCode 区域编码
     * @return 区域信息
     */
    Region getRegionByCode(String regionCode) throws Exception;

    /**
     * 根据区域类型获取区域列表
     * 
     * @param regionType 区域类型
     * @return 区域列表
     */
    List<Region> getRegionsByType(Integer regionType) throws Exception;

    /**
     * 获取所有启用的区域列表
     * 
     * @return 启用的区域列表
     */
    List<Region> getEnabledRegions() throws Exception;

    /**
     * 获取所有区域列表
     * 
     * @return 所有区域列表
     */
    List<Region> getAllRegions() throws Exception;

    /**
     * 根据用户权限获取区域列表
     * 
     * @param userId 用户ID
     * @param type 权限类型
     * @return 区域列表
     */
    List<Region> getRegionsByUserPermission(Long userId, Integer type) throws Exception;

    /**
     * 获取子区域列表
     * 
     * @param parentId 父区域ID
     * @return 子区域列表
     */
    List<Region> getChildRegions(Long parentId) throws Exception;

    /**
     * 获取区域层级路径
     * 
     * @param regionId 区域ID
     * @return 层级路径
     */
    List<Region> getRegionPath(Long regionId) throws Exception;

    /**
     * 获取所有父区域ID
     * 
     * @param regionId 区域ID
     * @return 父区域ID列表
     */
    List<Long> getAllParentRegionIds(Long regionId) throws Exception;

    /**
     * 获取所有子区域ID（包括子区域的子区域）
     * 
     * @param regionId 区域ID
     * @return 子区域ID列表
     */
    List<Long> getAllChildRegionIds(Long regionId) throws Exception;

    // ==================== 树形结构方法 ====================

    /**
     * 获取区域树形结构（按需加载）
     * 
     * @param parentId 父区域ID，null表示获取顶级区域
     * @return 区域树形列表
     */
    List<RegionTreeVO> getRegionTree(Long parentId) throws Exception;

    /**
     * 获取区域完整树形结构（递归查询所有子区域）
     * 注意：此方法仅用于特殊场景，一般情况下使用getRegionTree进行按需加载
     * 
     * @param parentId 父区域ID，null表示获取所有顶级区域
     * @return 完整的树形结构
     */
    List<RegionTreeVO> getCompleteRegionTree(Long parentId) throws Exception;

    // ==================== 统计方法 ====================

    /**
     * 获取区域统计信息
     * 
     * @param regionId 区域ID
     * @return 统计信息
     */
    RegionStatsVO getRegionStats(Long regionId) throws Exception;

    /**
     * 获取区域统计信息（所有区域）
     * 
     * @return 统计信息
     */
    RegionStatsVO getRegionStatistics() throws Exception;

    /**
     * 获取区域统计列表
     * 
     * @param regionId 区域ID，null表示获取所有
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 统计列表
     */
    List<RegionStatsVO> getRegionStatsList(Long regionId, String startDate, String endDate) throws Exception;

    /**
     * 刷新区域统计数据
     * 
     * @param regionId 区域ID
     * @return 是否成功
     */
    boolean refreshRegionStats(Long regionId) throws Exception;

    // ==================== 数据可视化方法 ====================

    /**
     * 获取地图标记数据
     * 
     * @param type 标记类型：region-区域，community-社区，building-楼栋
     * @param parentId 父区域ID
     * @return 地图标记数据
     */
    List<RegionVisualizationDTO.MapMarker> getMapMarkers(String type, Long parentId) throws Exception;

    /**
     * 获取区域边界数据
     * 
     * @param regionId 区域ID
     * @return 区域边界数据
     */
    RegionVisualizationDTO.RegionBoundary getRegionBoundary(Long regionId) throws Exception;

    /**
     * 获取区域面积热力图数据
     * 
     * @param parentId 父区域ID
     * @return 热力图数据
     */
    List<RegionVisualizationDTO.AreaHeatmap> getAreaHeatmap(Long parentId) throws Exception;

    /**
     * 获取区域人口统计
     * 
     * @param parentId 父区域ID
     * @return 人口统计数据
     */
    List<RegionVisualizationDTO.PopulationStats> getPopulationStats(Long parentId) throws Exception;

    /**
     * 获取社区分布统计
     * 
     * @param parentId 父区域ID
     * @return 社区分布数据
     */
    List<RegionVisualizationDTO.CommunityDistribution> getCommunityDistribution(Long parentId) throws Exception;

    /**
     * 获取楼栋房户趋势统计
     * 
     * @param regionId 区域ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 趋势数据
     */
    List<RegionVisualizationDTO.BuildingHouseholdTrend> getBuildingHouseholdTrend(Long regionId, String startDate, String endDate) throws Exception;

    /**
     * 地理信息查询
     * 
     * @param address 查询地址
     * @param longitude 经度
     * @param latitude 纬度
     * @return 地理查询结果
     */
    RegionVisualizationDTO.GeoSearchResult geoSearch(String address, BigDecimal longitude, BigDecimal latitude) throws Exception;

    /**
     * 根据经纬度范围查询区域信息
     * 
     * @param minLat 最小纬度
     * @param maxLat 最大纬度
     * @param minLng 最小经度
     * @param maxLng 最大经度
     * @return 区域列表
     */
    List<Region> geoQuery(BigDecimal minLat, BigDecimal maxLat, BigDecimal minLng, BigDecimal maxLng) throws Exception;

    // ==================== 验证方法 ====================

    /**
     * 检查区域编码唯一性
     * 
     * @param regionCode 区域编码
     * @param excludeRegionId 排除的区域ID
     * @return 是否唯一
     */
    boolean checkRegionCodeUnique(String regionCode, Long excludeRegionId) throws Exception;

    /**
     * 检查区域编码是否存在
     * 
     * @param regionCode 区域编码
     * @param excludeId 排除的区域ID
     * @return 是否存在
     */
    boolean checkRegionCodeExists(String regionCode, Long excludeId) throws Exception;

    // ==================== 缓存方法 ====================

    /**
     * 获取区域缓存键
     * 
     * @param regionId 区域ID
     * @return 缓存键
     */
    String getRegionCacheKey(Long regionId) throws Exception;

    /**
     * 清除区域缓存
     * 
     * @param regionId 区域ID
     */
    void clearRegionCache(Long regionId) throws Exception;

    /**
     * 清除所有区域缓存
     */
    void clearAllRegionCache() throws Exception;

    // ==================== Feign接口专用方法 ====================

    /**
     * 获取区域树形结构（Feign接口专用，跳过权限验证）
     * 
     * @param parentId 父区域ID，null表示获取顶级区域
     * @return 区域树形列表
     */
    List<com.smart.community.feign.region.dto.RegionTreeDTO> getRegionTreeForFeign(Long parentId) throws Exception;

    /**
     * 获取区域完整树形结构（Feign接口专用，跳过权限验证）
     * 
     * @param parentId 父区域ID，null表示获取所有顶级区域
     * @return 完整的树形结构
     */
    List<com.smart.community.feign.region.dto.RegionTreeDTO> getCompleteRegionTreeForFeign(Long parentId) throws Exception;

    /**
     * 根据区域ID获取区域信息（Feign接口专用，跳过权限验证）
     * 
     * @param regionId 区域ID
     * @return 区域信息
     */
    com.smart.community.feign.region.dto.RegionDTO getRegionByIdForFeign(Long regionId) throws Exception;

    /**
     * 根据区域编码获取区域信息（Feign接口专用，跳过权限验证）
     * 
     * @param regionCode 区域编码
     * @return 区域信息
     */
    com.smart.community.feign.region.dto.RegionDTO getRegionByCodeForFeign(String regionCode) throws Exception;

    /**
     * 根据区域类型获取区域列表（Feign接口专用，跳过权限验证）
     * 
     * @param regionType 区域类型
     * @return 区域列表
     */
    List<com.smart.community.feign.region.dto.RegionDTO> getRegionsByTypeForFeign(Integer regionType) throws Exception;

    /**
     * 获取子区域列表（Feign接口专用，跳过权限验证）
     * 
     * @param regionId 区域ID
     * @return 子区域列表
     */
    List<com.smart.community.feign.region.dto.RegionDTO> getChildRegionsForFeign(Long regionId) throws Exception;

    /**
     * 获取区域层级路径（Feign接口专用，跳过权限验证）
     * 
     * @param regionId 区域ID
     * @return 层级路径
     */
    List<com.smart.community.feign.region.dto.RegionDTO> getRegionPathForFeign(Long regionId) throws Exception;

    /**
     * 批量获取区域信息（Feign接口专用，跳过权限验证）
     * 
     * @param regionIds 区域ID列表
     * @return 区域信息列表
     */
    List<com.smart.community.feign.region.dto.RegionDTO> getRegionsByIdsForFeign(List<Long> regionIds) throws Exception;

    /**
     * 检查区域编码是否存在（Feign接口专用，跳过权限验证）
     * 
     * @param regionCode 区域编码
     * @param excludeRegionId 排除的区域ID
     * @return 是否存在
     */
    Boolean checkRegionCodeExistsForFeign(String regionCode, Long excludeRegionId) throws Exception;

    /**
     * 根据区域名称模糊查询区域列表（Feign接口专用，跳过权限验证）
     * 
     * @param regionName 区域名称
     * @return 区域列表
     */
    List<com.smart.community.feign.region.dto.RegionDTO> searchRegionsByNameForFeign(String regionName) throws Exception;

    /**
     * 获取区域统计信息（Feign接口专用，跳过权限验证）
     * 
     * @param regionId 区域ID
     * @return 统计信息
     */
    Object getRegionStatsForFeign(Long regionId) throws Exception;

    /**
     * 获取所有区域统计信息（Feign接口专用，跳过权限验证）
     * 
     * @return 所有区域统计信息
     */
    Object getAllRegionStatisticsForFeign() throws Exception;

    /**
     * 清除区域缓存（Feign接口专用，跳过权限验证）
     * 
     * @param regionId 区域ID
     * @return 清除结果
     */
    Boolean clearRegionCacheForFeign(Long regionId) throws Exception;

    /**
     * 清除所有区域缓存（Feign接口专用，跳过权限验证）
     * 
     * @return 清除结果
     */
    Boolean clearAllRegionCacheForFeign() throws Exception;

    /**
     * 刷新区域统计数据（Feign接口专用，跳过权限验证）
     * 
     * @param regionId 区域ID
     * @return 刷新结果
     */
    Boolean refreshRegionStatsForFeign(Long regionId) throws Exception;
} 